 #include "stdlib.h"
#include <stdio.h>
#include <iostream>
#include <libusb-1.0/libusb.h>
using namespace std;

//热插拔的回调监听函数
//不要在回调函数中调用可能阻塞的操作，否则可能造成libusb的其他函数执行失败
static int hotplug_callback(
    struct libusb_context *ctx,
    struct libusb_device *device,
    libusb_hotplug_event event,
    void *user_data) {
    //通过设备获取设备地址
    uint8_t deviceAddress = libusb_get_device_address(device);
    //enum libusb_hotplug_event {
    //     LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED = 0x01,
    //     LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT = 0x02 }
    if(event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED) {
        printf("设备连接 \n");
    } else if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) {
        printf("设备断开 \n");
    }
    return 0;
}

int main () {
  printf("testUSB\n");
  //libusb的上下文对象，初始化的时候需要使用
  libusb_context *context;
  //初始化libusb,要最先调用
  int ret = libusb_init(&context);
  if (ret != LIBUSB_SUCCESS) {
      printf("initialize libusb failed");
      return -1;
  }
  //判断当前的的库，是否支持热插拔
  if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
      printf("this version's libusb doesn't support hotplug");
      return -1;
  }
  //注册hotplug
  //需要监控的VID，设置为LIBUSB_HOTPLUG_MATCH_ANY，则不判断VID
  int vendor_id = LIBUSB_HOTPLUG_MATCH_ANY;
  //需要监控的PID 设置为LIBUSB_HOTPLUG_MATCH_ANY，则不判断PID
  int product_id = LIBUSB_HOTPLUG_MATCH_ANY;
  //需要监控的设备的class,设置为LIBUSB_HOTPLUG_MATCH_ANY，则不判断，与libusb_device_descriptor的class匹配
  //这个参数不是很懂
  int device_class = LIBUSB_HOTPLUG_MATCH_ANY;
  //设备需要监听的事件，插入和拔出
  libusb_hotplug_event event = static_cast<libusb_hotplug_event> (LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT);

  //typedef enum {
  //    LIBUSB_HOTPLUG_NO_FLAGS = 0,//只有在发生拔插的时候才会调用注册的回调函数
  //    LIBUSB_HOTPLUG_ENUMERATE = 1<<0,//在初始化前设备已经插入，也会调用注册的回调函数
  //} libusb_hotplug_flag;
  libusb_hotplug_flag flag = static_cast<libusb_hotplug_flag>(1);

  //句柄，具体啥作用目前未知
  libusb_hotplug_callback_handle handle;

  //设备回调过来的数据
  void *user_data;

  // int LIBUSB_CALL libusb_hotplug_register_callback(libusb_context *ctx,
  //                        libusb_hotplug_event events,
  //                        libusb_hotplug_flag flags,
  //                        int vendor_id, int product_id,
  //                        int dev_class,
  //                        libusb_hotplug_callback_fn cb_fn,
  //                        void *user_data,
  //                        libusb_hotplug_callback_handle *callback_handle);
  printf("libusb_hotplug_register_callback\n");
  int result_Register = libusb_hotplug_register_callback(context, 
        event, 
        flag, 
        vendor_id, 
        product_id, 
        device_class, 
        hotplug_callback, 
        &user_data, 
        &handle);
  if (result_Register != LIBUSB_SUCCESS) {
      printf("resigter hotplug_callback failed");
      return -1;
  } else {
      printf("resigter hotplug_callback successfully");
  }

  //注册了热插拔事件，必须要在循环中调用libusb_handle_events
  //在阻塞模式中处理任何挂起的事件。
  while(1) {
        //设置允许处理事件的超时时间
        printf("libusb_handle_events\n");
        libusb_handle_events(context);
  }

  //注销回调事件
  libusb_hotplug_deregister_callback(context, handle);
  libusb_exit(context);
  return 0;
}
